-module(sc_element).
-behaviour(gen_server).

-export([
    start_link/2,
    create/2,
    create/1,
    fetch/1,
    replace/2,
    delete/1
    ]).

%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
        terminate/2, code_change/3]).

-define(DEFAULT_LEASE_TIME, (60*60*24)).

-record(state, {
    value,               %% 映射的值
    lease_time,          %% 过期时间
    start_time           %% 映射时间
}).

start_link(Value, LeaseTime) ->
    gen_server:start_link(?MODULE, [Value, LeaseTime], []).

create(Value, LeaseTime) ->
    sc_sup:start_child(Value, LeaseTime).

create(Value) ->
    sc_sup:start_child(Value, ?DEFAULT_LEASE_TIME).

fetch(Pid) ->
    gen_server:call(Pid, fetch).

replace(Pid, Value) ->
    gen_server:cast(Pid, {replace, Value}).

delete(Pid) ->
    gen_server:cast(Pid, delete).


%%%===========================================================
%%%Callbacks
%%%===========================================================
init([Value, LeaseTime]) ->
    Now = calendar:local_time(),
    StartTime = calendar:datetime_to_gregorian_seconds(Now),
    {ok,
        #state{
            start_time = StartTime,
            lease_time = LeaseTime, 
            value = Value
        },
    time_left(StartTime, LeaseTime)
    }.

time_left(_StartTime, infinity) -> infinity;
time_left(StartTime, LeaseTime) ->
    Now = calendar:local_time(),
    NowTime = calendar:datetime_to_gregorian_seconds(Now),
    case (StartTime + LeaseTime) - NowTime of 
        Time when is_integer(Time) andalso Time > 0 ->
            Time * 1000;
        _ -> 0
    end.

%% 处理同步请求
handle_call(fetch, _From, State) ->
    #state{
        value = Value,
        lease_time = LeaseTime, 
        start_time = StartTime
    } = State,
    {reply, Value, time_left(StartTime, LeaseTime)}.

handle_cast({replace, Value}, State) ->
    #state{
        lease_time = LeaseTime,
        start_time = StartTime    
    } = State,
    NewState = State#state{value = Value},
    {noreply, NewState, time_left(StartTime, LeaseTime)};

%% 处理异步请求消息
handle_cast(delete, State) ->
    {stop, normal, State}.

handle_info(timeout, State) ->
    {stop, normal, State}.

terminate(_Resason, _State) -> 
    %% 销毁ets的映射
    sc_store:delete(self()),
    ok.
code_change(_OldVsn, State, _Extra) -> {ok, State}.